/*
 * @Author: 0x9DEFA478
 * @Date: 2025-07-27 00:34:36
 * @LastEditTime: 2025-09-14 00:11:26
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * 
 */
#ifndef hH_FIFO_HPP_
#define hH_FIFO_HPP_
#include <type_traits>
#include <utility>
#include <atomic>
#include <initializer_list>
#include "./H_Concurrency.hpp"




namespace H{

#if __cplusplus >= 202000L
  template<typename ItemType,Concept::event EventType=Event,Concept::lock LockType=Lock>
#else
  template<typename ItemType,typename EventType=Event,typename LockType=Lock>
#endif
  class FIFO{
    static_assert(std::is_default_constructible_v<ItemType>);
    static_assert(std::is_move_constructible_v<ItemType>);
    static_assert(std::is_move_assignable_v<ItemType>);
    static_assert(std::is_destructible_v<ItemType>);
    public:
      FIFO(size MaxCount):WriteIndex(0),ReadIndex(0),MaxCount(MaxCount),mem(new byte[sizeof(ItemType)*(MaxCount+1)]){}
      ~FIFO(){
        WriteLock.Lock();
        Clear();
        WriteLock.Unlock();
        delete[] mem;
      }

      FIFO(const FIFO&)=delete;
      FIFO(FIFO&&)=delete;


      /**
       * @brief 读取
       * @return 在读取不到数据返回ItemType的默认构造对象
       */
      ItemType Read(){
        ItemType r;
        size readIndex;

        readIndex=ReadIndex.load(std::memory_order::consume);
        if(WriteIndex.load(std::memory_order::relaxed)!=readIndex){
          ItemType* item;
          item=static_cast<ItemType*>(Pointer(readIndex));
          r=std::move(*item);
          item->~ItemType();
          if(readIndex<MaxCount){
            readIndex+=1;
          }else{
            readIndex=0;
          }
          ReadIndex.store(readIndex,std::memory_order::release);
          ReadEvent.Trigger();
        }

        return r;
      }

      /**
       * @brief 写入
       * @param Args... 用于构造ItemType的参数
       * @return 是否添加成功
       */
      template<typename... T_Arg>
      bool Write(T_Arg&&... Args){
        bool r;
        size writeIndex;
        size NextWrite;

        WriteLock.Lock();
        writeIndex=WriteIndex.load(std::memory_order::consume);
        if(writeIndex<MaxCount){
          NextWrite=writeIndex+1;
        }else{
          NextWrite=0;
        }
        r=NextWrite!=ReadIndex.load(std::memory_order::relaxed);
        if(r){
          new(Pointer(writeIndex))ItemType(std::forward<T_Arg>(Args)...);
          WriteIndex.store(NextWrite,std::memory_order::release);
          WriteEvent.Trigger();
        }
        WriteLock.Unlock();

        return r;
      }

      /**
       * @brief 写入
       * @param initializer_list 初始化列表
       * @return 是否添加成功
       */
      template<typename T>
      bool Write(std::initializer_list<T>&& initializer_list){
        return Write(initializer_list);
      }

      
      //空间使用量的信息不一定是即时的, 甚至不能代表最近某一个时刻的情况

      bool Empty()const{
        bool r;
        r=WriteIndex.load(std::memory_order::relaxed)==ReadIndex.load(std::memory_order::relaxed);
        return r;
      }

      bool Full()const{
        bool r;
        size NextWrite;
        NextWrite=WriteIndex.load(std::memory_order::relaxed);
        if(NextWrite<MaxCount){
          NextWrite++;
        }else{
          NextWrite=0;
        }
        r=NextWrite==ReadIndex.load(std::memory_order::relaxed);
        return r;
      }

      size EmptyCount()const{
        return MaxCount-Count();
      }

      size Count()const{
        size r;
        r=WriteIndex.load(std::memory_order::relaxed)-ReadIndex.load(std::memory_order::relaxed);
        if(r<0){
          r=MaxCount+1+r;
        }
        return r;
      }


      //Wait系列函数等待成功后也不一定能成功执行后续操作 主要用作让线程休眠

      void WaitForRead(){
        if(Empty()){
          WriteEvent.wait();
        }
      }

      bool WaitForRead(size Timeout){
        if(Empty()){
          return WriteEvent.Acquire(Timeout);
        }
        return true;
      }

      void WaitForWrite(){
        WriteLock.Lock();
        if(Full()){
          ReadEvent.Acquire();
        }
        WriteLock.Unlock();
      }

      bool WaitForWrite(size Timeout){
        bool r;
        r=true;
        WriteLock.Lock();
        if(Full()){
          r=ReadEvent.Acquire(Timeout);
        }
        WriteLock.Unlock();
        return r;
      }


      void Clear(){
        size readIndex;
        bool IsClear;

        IsClear=false;
        WriteLock.Lock();
        while((readIndex=ReadIndex.load(std::memory_order::consume))!=WriteIndex.load(std::memory_order::relaxed)){
          static_cast<ItemType*>(Pointer(readIndex))->~ItemType();
          if(readIndex<MaxCount){
            readIndex+=1;
          }else{
            readIndex=0;
          }
          ReadIndex.store(readIndex,std::memory_order::release);
          IsClear=true;
        }

        if(IsClear){
          ReadEvent.Trigger();
        }
        WriteLock.Unlock();
      }

    private:
      void* Pointer(size Index){return static_cast<void*>(&mem[sizeof(ItemType)*Index]);}

    private:
      std::atomic<size> WriteIndex;
      std::atomic<size> ReadIndex;
      const size MaxCount;
      byte* const mem;
      EventType ReadEvent;
      EventType WriteEvent;
      LockType WriteLock;
  };

}




#endif //hH_FIFO_HPP_
